package estrategia;

import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;

import javax.vecmath.Point3d;

import monitor.ManagerObjetos;

import comunicacion.Conector;
import comunicacion.ParametrosEntorno;

public class Predictor {
	
	private int miRobot;
	private Historial[] historialesOponentes;
	private Conector entorno;
	private ManagerObjetos managerObjetos;
	private Utiles utiles;
	private PredictorDaemon daemon;
	
	public Predictor(Conector entorno, ManagerObjetos managerObjetos) throws IOException {
		this.miRobot = ParametrosGlobales.MI_ROBOT;
		this.entorno = entorno;
		this.managerObjetos = managerObjetos;
		this.utiles = new Utiles(entorno);
		
		historialesOponentes = new Historial[ParametrosGlobales.CANTIDAD_OBJETOS];
		for (int i=0; i<historialesOponentes.length; i++) {
			historialesOponentes[i] = new Historial(entorno, i);
		}
				
		// Inicialmente los historiales no aparecen vacios,
		// sino llenos con la posicion actual de cada uno
		for (int i=0; i<5; i++) {
			try {
				actualizarHistoriales(entorno.getCoordenadasObjetos());
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		daemon = new PredictorDaemon(entorno, this);
		daemon.start();
	}
	
	public void actualizarHistoriales(Point3d[] nuevasCoordenadas) throws IOException {
		for (int i=0; i<historialesOponentes.length; i++) {
			if (i < nuevasCoordenadas.length) {
				int idObjeto = i;
				if (idObjeto>ParametrosGlobales.MI_ROBOT)
					idObjeto++;
				
				if (!managerObjetos.estaEliminado(idObjeto))
					historialesOponentes[i].agregar(nuevasCoordenadas[i]);
				else {
					historialesOponentes[i].limpiar();
				}
			}
		}
	}

	
	public Point3d predecirPosicion(int idObjeto) throws IOException {
		double RELACION_DISTANCIA_PASOS_HACIA_FUTURO = 15;
		
		Point3d posMiRobot = entorno.getCoordenadas();
		Point3d objeto = entorno.getCoordenadas(idObjeto);
		int pasosHaciaFuturo = 0;
		
		if (managerObjetos.esEnemigo(idObjeto)) {
			double distancia = utiles.distanciaEuclidea(posMiRobot, objeto);
			pasosHaciaFuturo = (int) (distancia * RELACION_DISTANCIA_PASOS_HACIA_FUTURO);
		}
		
		Point3d destino = predecirPosicion(idObjeto, pasosHaciaFuturo);
		
		return destino;
		
		//return entorno.getCoordenadas(idObjeto);
	}
	
	public Point3d predecirPosicion(int idObjeto, int pasos) {
		int indice = idObjeto;
		if (indice == miRobot) {
			System.err.println("Estas prediciendo la posicion de tu bicho, no se si esta bueno eso");
		}
		if (indice > miRobot) {
			indice--;
		}
		
		if (historialesOponentes[indice] == null) {
			System.err.println("Accediendo a historial " + indice + ", que no existe");
		}
		
		Historial historial = historialesOponentes[indice];
		double rotacionPromedio = historial.getRotacionPromedio();
		double velocidadPromedio = historial.getVelocidadPromedio();
		Point3d posicionActual = historial.getUltimaPosicion();
		
		Point3d posicionFutura = new Point3d();
		posicionFutura.x = posicionActual.x + pasos*velocidadPromedio*Math.cos(rotacionPromedio);
		posicionFutura.y = posicionActual.y + pasos*velocidadPromedio*Math.sin(rotacionPromedio);
		posicionFutura.z = rotacionPromedio;
		
		if (posicionFutura.x <= ParametrosEntorno.POSICION_PARED_IZQUIERDA)
			posicionFutura.x = ParametrosEntorno.POSICION_PARED_IZQUIERDA;
		else if (posicionFutura.x >= ParametrosEntorno.POSICION_PARED_DERECHA)
			posicionFutura.x = ParametrosEntorno.POSICION_PARED_DERECHA;
		
		if (posicionFutura.y <= ParametrosEntorno.POSICION_PARED_TRASERA)
			posicionFutura.y = ParametrosEntorno.POSICION_PARED_TRASERA;
		else if (posicionFutura.y >= ParametrosEntorno.POSICION_PARED_DELANTERA)
			posicionFutura.y = ParametrosEntorno.POSICION_PARED_DELANTERA;
			
		//System.out.print("Prediccion para " + idObjeto + " en " + pasos + " pasos: (" + 
		//		posicionActual.x + ", " + posicionActual.y + ", " + posicionActual.z + ") => ");
		//System.out.println("(" + posicionFutura.x + ", " + posicionFutura.y + ", " + posicionFutura.z + ")");
		
		return posicionFutura;
	}
	
	public boolean ataqueInminente(int idObjeto) throws IOException {
		int MAXIMA_CANTIDAD_PASOS = 10;
		double RADIO_MI_ROBOT = 0.10;
		
		Point3d posMiRobot = entorno.getCoordenadas();
		
		for (int pasos=2; pasos<MAXIMA_CANTIDAD_PASOS; pasos++) {
			if (managerObjetos.esEnemigo(idObjeto)) {
				Point3d posEnemigo = predecirPosicion(idObjeto, pasos);
				
				if (utiles.distanciaEuclidea(posMiRobot, posEnemigo) < RADIO_MI_ROBOT) {
					System.out.print("El enemigo " + idObjeto + " me esta atacando");
					return true;
				}
			}
		}
		
		return false;
	}
}
